package FeedMaker;

import jBittorrentAPI.TorrentProcessor;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils;


import android.os.Environment;
import android.util.Pair;

public class DdanjiEntry 
{
	public String url_="";
	public String title_="";
	public String subtitle_="";
	public String length_="";
	public String pubDate_ = "";
	public int number_ = 0;
	public int torrent_size_ = 0;
	
	private String filename_ = "";
	private boolean downloaded_ = false;
	private boolean uploaded_ = false;
	private boolean isFaulty_ = false;
	private float progress_ = 0;
	
	private long progress_interval_ = 300;
	
	synchronized public String getFileName() { return new String(filename_); }
	
	synchronized public boolean IsDownloaded() { return downloaded_; }
	
	synchronized public boolean IsUploaded() { return uploaded_; }
	
	synchronized public boolean IsFaulty() { return isFaulty_; }
	
	synchronized public float getProgress() { return progress_; }
	
	synchronized private void setDownloaded( boolean downloaded ) { downloaded_ = downloaded; }
	
	synchronized private void setUploaded( boolean uploaded ) { uploaded_ = uploaded; }
	
	synchronized private void setFaulty( boolean isFaulty ) { isFaulty_ = isFaulty; }
	
	synchronized private void setProgress( float progress ) { progress_ = progress; }
	
	synchronized public void setFileName( String filePath ) { filename_ = filePath; }
	
	public DdanjiEntry() {
		
	}
	
	public DdanjiEntry(DdanjiEntry other)
	{
		if( other != null )
		{
			url_ = other.url_;
			title_ = other.title_;
			subtitle_ = other.subtitle_;
			length_ = other.length_;
			pubDate_ = other.pubDate_;
			number_ = other.number_;
			torrent_size_ = other.torrent_size_;
			setFileName( other.getFileName() );
			setDownloaded( other.IsDownloaded() );
			setUploaded( other.IsUploaded() );
			setFaulty( other.IsFaulty() );
			setProgress( other.getProgress() );
		}
	}
	
	public String toData()
	{
		return url_ + "`'" + title_ + "`'" + subtitle_ + "`'" + length_ + "`'" + pubDate_ 
				+ "`'" + Integer.toString( number_ )
				+ "`'" + Integer.toString( torrent_size_ )
				+ "`'" + getFileName()
				+ "`'" + Boolean.toString( IsDownloaded() )
				+ "`'" + Boolean.toString( IsUploaded() )
				+ "`'" + "0";
		
	}
	
	public void fromData( String data )
	{
		if( data != null )
		{
			String[] args = data.split("`'");
			
			if( args.length >= 9 )
			{
				url_ = args[0];
				title_ = args[1];
				subtitle_ = args[2];
				length_ = args[3];
				pubDate_ = args[4];
				number_ = Integer.parseInt( args[5] );
				torrent_size_ = Integer.parseInt( args[6] );
				setFileName( args[7] );
				setDownloaded( Boolean.parseBoolean( args[8] ) );
				setUploaded( Boolean.parseBoolean( args[9] ) );
				setFaulty( false );
			}
		} 
	}
	
	private Date get_file_date( HttpResponse response, String dateString )
	{
		Header header = response.getFirstHeader( dateString );
		if( header != null )
		{
			String tmp = header.getValue();
			
			try {
				return DateUtils.parseDate( tmp );
			} catch (DateParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		return null;
	}
	
	public boolean download( String feed_title, String save_path )
	{
		boolean changed = false;
		
		if( IsDownloaded() == false && !IsFaulty() )
		{
			
				try 
				{
					HttpClient httpclient = new DefaultHttpClient();
					HttpGet httpget = new HttpGet(url_);
					HttpResponse response = httpclient.execute(httpget);
					HttpEntity entity = response.getEntity();
					
					long downloadedSize = 0;
					long totalSize = 0;
					
					String filename = "";
					//Date creation_date=null;
					Date modification_date=null;
					//Date read_date=null;
					//Date quoted_date=null;
					
					if (entity != null) {    
						InputStream instream = entity.getContent();
						totalSize = entity.getContentLength();
					
						for( Header header : response.getHeaders("Content-Disposition") )
						{
							for( org.apache.http.HeaderElement elem : header.getElements() )
							{
								NameValuePair r = elem.getParameterByName("filename");
								
								if( r != null )
								{
									filename = r.getValue();
									filename = filename.replace("\"", "");
								}
							}
							
							if( filename.length() > 0 )
								break;
						}
						
						if( filename.length() == 0 )
						{
							String ext = url_.substring( url_.lastIndexOf(".") );
							filename = title_+ext;
						}
						
						//creation_date		= get_file_date( response, "creation-date" );
						modification_date	= get_file_date( response, "last-modified" );
						//read_date			= get_file_date( response, "read-date" );
						//quoted_date			= get_file_date( response, "quoted-date" );						
						
						File path = new File(Environment.getExternalStorageDirectory() + "/" + save_path + feed_title + "/" );
					
						if( !path.isDirectory() )
							path.mkdirs();						
						
						File file = new File( Environment.getExternalStorageDirectory(), save_path + feed_title + "/" + filename );
						
						if( file.isFile() )
							file.delete();
						
						setFileName( filename );
						
						FileOutputStream fileOutput = new FileOutputStream(file);
						
						
						long lastProgress = 0;
						int l;
						byte[] tmp = new byte[1024];
						while ((l = instream.read(tmp)) != -1)
						{							
							fileOutput.write(tmp, 0, l);
							
							downloadedSize += l;
							
							if( downloadedSize >= totalSize )
								break;
							
							if( System.currentTimeMillis() - lastProgress > progress_interval_ )
							{
								lastProgress = System.currentTimeMillis();
								setProgress( downloadedSize/(float)totalSize * 100 );
							}
						}
												
						if( modification_date != null )
							file.setLastModified( modification_date.getTime() );							
						
						setProgress( 100 );
						
						fileOutput.close();
						
						instream.close();
						
						setDownloaded(true);
						
						changed = true;
					}		
				} 
				catch (IOException e) 
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
					
					//setFaulty( true );
				}
			
		}
		
		return changed;
	}
	
	static String toUTF8( String str )
	{
		try {
			return URLEncoder.encode( str.replace(" ", "_"), "UTF-8" ).replace("+","%20");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return str;
	}
	
	public boolean upload( String feed_title, String save_path )
	{
		if( IsDownloaded() != true || IsFaulty() || IsUploaded() == true )
			return false;
			
		
		if( !DropBoxHandler.inst().isReady() )
			return false;
		
		Pair< String, String > result = make_torrent( feed_title, save_path );
		
		String torrent_file_path = result.first;
		String target_file_name = result.second;
		
		if( torrent_file_path.length() > 0 )
		{			
			 if( DropBoxHandler.inst().upload(torrent_file_path, "/" + toUTF8( feed_title ) + "/" + toUTF8( title_ ) + ".torrent" ) )
             {
             	File media_file = new File( target_file_name );
             	File torrent_file = new File( torrent_file_path );
             	
             	torrent_size_ = (int)torrent_file.length();
             	
             	media_file.delete();
             	torrent_file.delete();
             	
             	setUploaded(true);
             	
             	return true;
             }
		}		    
        
        return false;
	}
	
	private Pair<String, String> make_torrent( String feed_title, String save_path )
	{			
		TorrentProcessor tp = new TorrentProcessor();
		
        tp.setAnnounceURL( "udp://tracker.publicbt.com:80/announce" );
        
        tp.addTracker("udp://tracker.publicbt.com:80/announce");
        tp.addTracker("udp://tracker.openbittorrent.com:80/announce");
        tp.addTracker("udp://tracker.istole.it:80/announce");
        tp.addTracker("udp://tracker.1337x.org:80/announce");
        tp.addTracker("udp://11.rarbg.com/announce");
        
        tp.setName( title_.replace( " ", "_" ) );
       
        
        ArrayList<String> files = new ArrayList<String>();

        String target_file_name = Environment.getExternalStorageDirectory() + "/" + save_path + feed_title + "/" + getFileName();
        files.add( target_file_name );
        
        try {
			tp.addFiles( files );
			tp.setCreator( "ddanji_feedmaker" );
	        tp.setComment( "" );
	        tp.setCreationDate( (new Date()).getTime() );
	        tp.setEncoding("UTF-8");
	        
	        long piece_size = 16*1024;
	        
	        File targetFile = new File( target_file_name );
	        
	        if( targetFile.isFile() && targetFile.length() > 1024 )
	        {
	        	while( (targetFile.length() / (piece_size)) > 1000 )
		        {
		        	piece_size *= 2;
		        }
		        
		        if( piece_size > 2*1024*1024 )
		        	piece_size = 2*1024*1024;
		        
		        tp.setPieceLength((int)(piece_size));
		        
		        targetFile = null;
		        
		        tp.addWebSeed( url_ );
		        
		        try
		        {
		            tp.generatePieceHashes();
		            
		            String torrent_file_path = Environment.getExternalStorageDirectory() + "/" + save_path + feed_title + "/" + title_ + ".torrent";
		            
		            FileOutputStream fos = new FileOutputStream( torrent_file_path );
		            fos.write(tp.generateTorrent());
		            fos.close();
		            
		            return new Pair< String, String >( torrent_file_path, target_file_name );
		        }
		        catch( Exception e )
		        {
		        	e.printStackTrace();
		        }
	        }
	        else
	        {
	        	if( targetFile.isFile() )
	        		targetFile.delete();
	        	
	        	setDownloaded(false);
	        }
        }
        catch( Exception e )
        {
        	e.printStackTrace();
        }

        return new Pair<String,String>("","");
	}
}
